//== SAGITTARIUS ============================================================================

//== FILEDOC =========================================================================

/** @file builtinfun.h
  * @brief builtins
  */

//== BEGINNING OF CODE ===============================================================

#ifndef __SAGUTTARUIS__BUILTIN_FUN__H_
#define __SAGUTTARUIS__BUILTIN_FUN__H_

//== INCLUDES ========================================================================

#include "sagittarius/core/SagittariusCore.h"
#include "sagittarius/symtab/symtab.h"
#include "sagittarius/types/types.h"
#include "sagittarius/builtins/builtins.h"
#include "sagittarius/io/io.h"

#ifdef __cplusplus
extern "C" {
#endif

//typedef struct __sg_session sg_session;

typedef struct {
    /// Types
    struct __builtin_type_ctx* bt;
    //-- Functions --
    sg_fun_val* empty;
    sg_name_val* empty_nm;
    
    sg_fun_val* tostr;
} builtin_fun_ctx;

builtin_fun_ctx* create_builtin_fun_ctx(builtin_type_ctx* bt);

void install_builtin_fun_syms(builtin_fun_ctx* bf, symtab* st);

void release_builtin_fun_ctx(builtin_fun_ctx* bf);

sg_standard_protos* create_builtin_protos(builtin_type_ctx* bt, builtin_fun_ctx* bf);

//-- Builtins --

/// Create "empty"
sg_value* bf_empty();

/// Convert to string repr (member fun)
sg_value* sg_bf_tostr(void* ctx, sg_value* self);

sg_fun_val* bf_create_fun();

void bf_release_fun(sg_fun_val* f);

/// Create grav lens
sg_mir_val* bf_create_mir(sg_value* o, symcode s);

/// Create name-value
sg_name_val* bf_create_name();

/// release name-value
void bf_release_name(sg_name_val* nm);

/// call0
sg_value* bf_do_call0(sg_fun_val* f);

/// call1
sg_value* bf_do_call1(sg_fun_val* f, sg_value* a1);

sg_fctx_val* bf_create_fctx();

void bf_init_fctx(sg_fctx_val* c);

void bf_release_fctx(sg_fctx_val* c);

void bf_fctx_grow(sg_fctx_val* c);

int bf_sym_in_fctx(sg_fctx_val* c, symcode s);

sg_name_val* bf_fctx_get_local(sg_fctx_val* c, symcode s);

sg_name_val* bf_fctx_insert_sym(sg_fctx_val* c, symcode s);

void bf_dump_fctx(int fd, sg_fctx_val* c, symtab* st, uint64 ind);

/// Internal: symbol assignment
sg_value* bf_do_assn(sg_value** a, sg_value* b);

sg_value* bf_do_faccessr(sg_value* a, symcode s);

sg_value** bf_do_faccessl(sg_value* a, symcode s);

// does not cause hidden class transition (modify type in-place)
sg_value** bf_do_faccessl_freeze(sg_value* a, symcode s);

void sg_dump_fun_val(sg_value* f, symcode s);

void sg_dump_uint64(uint64 i);

CReal sg_get_real_scalar(sg_value* obj);

#ifdef __cplusplus
}//extern "C"
#endif

#endif
